﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using Hxj.Tools.EntityDesign.Model;
using System.Xml;
using System.Windows.Forms;
using Dos.ORM;
using Dos.ORM.Common;
using Hxj.Tools.EntityDesign;

namespace Dos.Tools.Common
{
    public class GenDAL
    {
        public bool GetByView { get; set; }
        public string ViewName { get; set; }
        public string Tbname { get; set; }

        private List<Hxj.Tools.EntityDesign.Model.ColumnInfo> _columns = new List<Hxj.Tools.EntityDesign.Model.ColumnInfo>();

        private string _tableName;
        private string _dbType;

        private string _nameSpace = "DAL.Model";

        private string _className;

        private bool _isView = false;

        private bool _isSZMDX = false;
        private bool _isNewModel = false;
        public GenDAL(string tableName, string nameSpace, string className, List<Hxj.Tools.EntityDesign.Model.ColumnInfo> columns, bool isView, bool isSZMDX, string dbType = null, bool isNewModel = false)
        {
            _isSZMDX = isSZMDX;
            _className = Utils.ReplaceSpace(className);
            _nameSpace = Utils.ReplaceSpace(nameSpace);
            _tableName = tableName;
            _dbType = dbType;
            _isNewModel = isNewModel;
            if (_isSZMDX)
            {
                _className = Utils.ToUpperFirstword(_className);
            }
            _isView = isView;

            foreach (Hxj.Tools.EntityDesign.Model.ColumnInfo col in columns)
            {
                col.ColumnName = Utils.ReplaceSpace(col.ColumnName);
                if (_isSZMDX)
                {
                    col.ColumnName = Utils.ToUpperFirstword(col.ColumnName);
                    TableName = Utils.ToUpperFirstword(TableName);
                    ViewName = Utils.ToUpperFirstword(ViewName);
                }

                col.DeText = Utils.ReplaceSpace(col.DeText);
                _columns.Add(col);
            }
        }

        public List<Hxj.Tools.EntityDesign.Model.ColumnInfo> Columns
        {
            get { return _columns; }
            set { _columns = value; }
        }
        public string TableName
        {
            get { return _tableName; }
            set { _tableName = value; }
        }
        public string NameSpace
        {
            get { return _nameSpace; }
            set { _nameSpace = value; }
        }
        public string ClassName
        {
            get { return _className; }
            set { _className = value; }
        }
        public string DbType
        {
            get { return _dbType; }
            set { _dbType = value; }
        }
        public bool IsView
        {
            get { return _isView; }
            set { _isView = value; }
        }

        public string Builder()
        {

            if (string.IsNullOrEmpty(ViewName))
            {
                ViewName = TableName;
            }
            if (_isSZMDX)
            {
                ViewName = Utils.ToUpperFirstword(ViewName);
            }
            Columns = DbToCS.DbtoCSColumns(Columns, DbType);

            StringPlus plus = new StringPlus();
            plus.AppendLine("//------------------------------------------------------------------------------");
            plus.AppendLine("// <auto-generated>");
            plus.AppendLine("//     此代码由工具生成。");
            plus.AppendLine("//     运行时版本:" + Environment.Version.ToString());
            plus.AppendLine("//     对此文件的更改可能会导致不正确的行为，并且如果");
            plus.AppendLine("//     重新生成代码，这些更改将会丢失。");
            plus.AppendLine("// </auto-generated>");
            plus.AppendLine("//------------------------------------------------------------------------------");
            plus.AppendLine();
            plus.AppendLine();
            //plus.AppendLine("using DAL.Base;");
            plus.AppendLine("using System;");
            plus.AppendLine("using System.Collections.Generic;");
            plus.AppendLine("using System.Linq;");
            plus.AppendLine("using System.Text;");
            plus.AppendLine("using System.Threading.Tasks;");
            plus.AppendLine("using " + NameSpace + ".DAL.Models;");
            plus.AppendLine("using Dos.ORM;");
            plus.AppendLine("using " + NameSpace + ".Common.Base;");
            plus.AppendLine();
            plus.AppendLine("namespace " + NameSpace + ".DAL");
            plus.AppendLine("{");
            plus.AppendLine();
            if (GetByView)
            {
                plus.AppendSpaceLine(1, "public  class " + ClassName + " : DALBASE<" + TableName + ", " + ViewName + "," + TableName + "_Condition>");
            }
            else
            {
                plus.AppendSpaceLine(1, "public  class " + ClassName + " : DALBASE<" + TableName + "," + TableName + "_Condition>");
            }


            plus.AppendSpaceLine(1, "{");
            plus.AppendSpaceLine(2, "public " + ClassName + "(DbSession DB) : base(DB) { }");
            Tbname = TableName;
            //查询
            //if (GetByView)
            //{
            //    TableName = ViewName;
            //}
            plus.Append(GenSelect());
            //TableName = Tbname;
            plus.AppendLine();

            //插入
            plus.Append(GenCreate());
            plus.AppendLine();
            //更新
            plus.Append(GenUpdate());
            plus.AppendLine();
            //删除
            plus.Append(GenDel());
            plus.AppendLine();
            //查询条件      
            plus.Append(GenWhere());
            //if (GetByView)
            //{
            //    TableName = ViewName;
            //    plus.Append(GenWhere());
            //    TableName = Tbname;
            //}
            plus.AppendLine();

            //条件
            //plus.Append(GenOrderBy());


            plus.AppendSpaceLine(1, "}");
            plus.AppendLine("}");
            plus.AppendLine("");
            return plus.ToString();
        }
        private string GenSelect()
        {
            StringPlus plus = new StringPlus();

            //plus.AppendSpaceLine(2, "#region 查询");
            var PKColumns = Columns.FindAll(p => p.IsPK);//主键列表

            //#region First
            //plus.AppendSpaceLine(2, string.Format("public {0} First({1}_Condition condition)", TableName, TableName));
            //plus.AppendSpaceLine(2, "{");
            //plus.AppendSpaceLine(3, "var where = BuildWhere(condition);");
            //plus.AppendSpaceLine(3, "var orderBy = BulidOrderBy(condition);");
            //plus.AppendSpaceLine(3, string.Format("var ret = Db.Context.From<{0}>()", TableName));
            //plus.AppendSpaceLine(4, ".Top(1)");
            //plus.AppendSpaceLine(4, ".OrderBy(orderBy)");
            //plus.AppendSpaceLine(4, ".Where(where)");
            //plus.AppendSpaceLine(4, ".ToList();");
            //plus.AppendSpaceLine(3, " if (ret.Count == 0)");
            //plus.AppendSpaceLine(4, "return null;");
            //plus.AppendSpaceLine(3, "return ret[0];");
            //plus.AppendSpaceLine(2, "}");
            //#endregion

            #region Get
            if (PKColumns.Count != 0)
            {
                plus.AppendSpace(2, string.Format("public {0} Get(", ViewName));
                foreach (var item in PKColumns)
                {
                    plus.Append(item.TypeName + " " + item.ColumnName + ", ");
                }
                plus.Remove(plus.Value.Length - 2, 2);
                plus.Append(")");
                plus.AppendLine();
                plus.AppendSpaceLine(2, "{");
                plus.AppendSpaceLine(3, string.Format("var condition = new {0}_Condition", TableName));
                plus.AppendSpaceLine(3, "{");
                for (int i = 0; i < PKColumns.Count; i++)
                {
                    plus.AppendSpace(4, string.Format("{0} = {1}", PKColumns[i].ColumnName, PKColumns[i].ColumnName));
                    if (i < PKColumns.Count - 1)
                    {
                        plus.Append(",");
                    }
                    plus.AppendLine();
                }
                plus.AppendSpaceLine(3, "};");
                plus.AppendSpaceLine(3, "return Get(condition);");
                plus.AppendSpaceLine(2, "}");
            }

            if (PKColumns.Count == 1)
            {
                plus.AppendSpace(2, string.Format("public List<{0}> GetList(", ViewName));
                plus.Append("List<");
                plus.Append(PKColumns[0].TypeName);
                plus.Append("> ");
                plus.Append(PKColumns[0].ColumnName);
                plus.Append(")");
                plus.AppendLine();
                plus.AppendSpaceLine(2, "{");
                plus.AppendSpaceLine(3, string.Format(" return DB.From<{0}>().Where(p => p.{1}.In({2})).ToList();", TableName, PKColumns[0].ColumnName, PKColumns[0].ColumnName));
             
                plus.AppendSpaceLine(2, "}");
            }
            #endregion



            #region Exist
            //plus.AppendSpaceLine(2, string.Format("public bool Exist({0}_Condition condition)", TableName));
            //plus.AppendSpaceLine(2, "{");
            //plus.AppendSpaceLine(3, "return Count(condition) != 0;");
            //plus.AppendSpaceLine(2, "}");
            #endregion

            #region Exist Key
            if (PKColumns.Count != 0)
            {
                plus.AppendSpace(2, "public bool Exist(");
                foreach (var item in PKColumns)
                {
                    plus.Append(item.TypeName + " " + item.ColumnName + ", ");
                }
                plus.Remove(plus.Value.Length - 2, 2);
                plus.Append(")");
                plus.AppendLine();
                plus.AppendSpaceLine(2, "{");
                plus.AppendSpace(3, string.Format("return DB.Exists<{0}>(p => ", TableName));
                foreach (var item in PKColumns)
                {
                    plus.Append("p." + item.ColumnName + " == " + item.ColumnName + " && ");
                }
                plus.Remove(plus.Value.Length - 4, 4);
                plus.Append(");");
                plus.AppendLine();
                plus.AppendSpaceLine(2, "}");
            }
            #endregion



            //plus.AppendSpaceLine(2, "#endregion");


            return plus.ToString();
        }

        string GenCreate()
        {
            StringPlus sb = new StringPlus();

            //sb.AppendSpaceLine(2, "#region 插入");

            //#region Create model
            //sb.AppendSpaceLine(2, string.Format("public int Create({0} model)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "return Db.Context.Insert(model);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            //#region Create model list
            //sb.AppendSpaceLine(2, string.Format("public int Create(List<{0}> models)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "return Db.Context.Insert(models);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            //sb.AppendSpaceLine(2, "#endregion");

            return sb.Value;
        }

        string GenUpdate()
        {
            StringPlus sb = new StringPlus();
            //sb.AppendSpaceLine(2, "#region 更新");

            //#region Update
            //sb.AppendSpaceLine(2, string.Format("public int Update({0} model)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "model.Attach();");
            //sb.AppendSpaceLine(3, "return Db.Context.Update(model);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            //#region Update List
            //sb.AppendSpaceLine(2, string.Format("public int Update(List<{0}> models)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "models.ForEach(p => p.Attach());");
            //sb.AppendSpaceLine(3, "return Db.Context.Update(models);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            //#region Update All
            //sb.AppendSpaceLine(2, string.Format("public int UpdateAll({0} model, {1}_Condition condition)", TableName, TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "model.Attach();");
            //sb.AppendSpaceLine(3, "var where = BuildWhere(condition);");
            //sb.AppendSpaceLine(3, " return Db.Context.UpdateAll(model, where);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            //sb.AppendSpaceLine(2, "#endregion");
            return sb.Value;

        }

        string GenDel()
        {
            var PKColumns = Columns.FindAll(p => p.IsPK);//主键列表
            StringPlus sb = new StringPlus();
            //sb.AppendSpaceLine(2, "#region 删除");

            //#region Delete Condition
            //sb.AppendSpaceLine(2, string.Format("public int Delete({0}_Condition condition)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "var where = BuildWhere(condition);");
            //sb.AppendSpaceLine(3, "return Db.Context.Delete<" + TableName + ">(where);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            //#region Delete Model
            //sb.AppendSpaceLine(2, string.Format("public int Delete({0} model)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "return Db.Context.Delete(model);");
            //sb.AppendSpaceLine(2, "}");
            //#endregion

            #region Delete Key
            if (PKColumns.Count != 0)
            {
                sb.AppendSpace(2, "public int Delete(");
                foreach (var item in PKColumns)
                {
                    sb.Append(item.TypeName + " " + item.ColumnName + ", ");
                }
                sb.Remove(sb.Value.Length - 2, 2);
                sb.Append(")");
                sb.AppendLine();
                sb.AppendSpaceLine(2, "{");

                sb.AppendSpace(3, string.Format("return DB.Delete<{0}>(p => ", TableName));
                foreach (var item in PKColumns)
                {
                    sb.Append("p." + item.ColumnName + " == " + item.ColumnName + " && ");
                }
                sb.Remove(sb.Value.Length - 4, 4);
                sb.Append(");");
                sb.AppendLine();
                sb.AppendSpaceLine(2, "}");
            }
            if (PKColumns.Count == 1)
            {
                sb.AppendSpace(2, "public int Delete(List<");
                sb.Append(PKColumns[0].TypeName);
                sb.Append("> ");
                sb.Append(PKColumns[0].ColumnName);
                sb.Append(")");
                sb.AppendLine();
                sb.AppendSpaceLine(2, "{");
                sb.AppendSpace(3, string.Format("return DB.Delete<{0}>(p => ", TableName));
                sb.Append("p." + PKColumns[0].ColumnName + ".In( " + PKColumns[0].ColumnName + " )");
                sb.Append(");");
                sb.AppendLine();
                sb.AppendSpaceLine(2, "}");
            }
            #endregion
            //sb.AppendSpaceLine(2, "#endregion");
            return sb.Value;
        }

        string GenWhere()
        {
            StringPlus sb = new StringPlus();
            sb.AppendSpaceLine(2, "#region 私有方法");

            #region Where
            sb.AppendSpaceLine(2, string.Format(" protected override WhereClip BuildWhere({0}_Condition condition)", TableName));
            sb.AppendSpaceLine(2, "{");
            sb.AppendSpaceLine(3, "WhereClipBuilder where = new WhereClipBuilder();");

            foreach (var col in Columns)
            {
                if (col.TypeName.ToLower() == "string")
                {
                    sb.AppendSpaceLine(3, "if (!string.IsNullOrEmpty(condition." + col.ColumnName + "))");
                    //sb.AppendSpaceLine(3, "{");
                }
                else
                {
                    sb.AppendSpaceLine(3, "if (condition." + col.ColumnName + " != null)");
                    //sb.AppendSpaceLine(3, "{");
                }
                //sb.AppendSpaceLine(4, "where.And(" + TableName + "._." + col.ColumnName + " == condition." + col.ColumnName + ");");
                sb.AppendSpaceLine(4, "where.And(new WhereClip(\"`" + col.ColumnName + "` = @" + col.ColumnName + "\",new Parameter(\"@" + col.ColumnName + "\",condition." + col.ColumnName + ")));");
                //如果是datetime
                if (col.TypeName.ToLower().Contains("datetime"))
                {
                    sb.AppendSpaceLine(3, "if (condition." + col.ColumnName + "_Start != null)");
                    //sb.AppendSpaceLine(4, "where.And(" + TableName + "._." + col.ColumnName + " >= condition." + col.ColumnName + "_Start);");
                    sb.AppendSpaceLine(4, "where.And(new WhereClip(\"`" + col.ColumnName + "` >= @" + col.ColumnName + "_Start\", new Parameter(\"@" + col.ColumnName + "_Start\", condition." + col.ColumnName + "_Start)));");
                    sb.AppendSpaceLine(3, "if (condition." + col.ColumnName + "_End != null)");
                    // sb.AppendSpaceLine(4, "where.And(" + TableName + "._." + col.ColumnName + " <= condition." + col.ColumnName + "_End);");
                    sb.AppendSpaceLine(4, "where.And(new WhereClip(\"`" + col.ColumnName + "` <= @" + col.ColumnName + "_End\", new Parameter(\"@" + col.ColumnName + "_End\", condition." + col.ColumnName + "_End)));");
                }


                //sb.AppendSpaceLine(3, "}");
            }
            sb.AppendSpaceLine(3, "return where.ToWhereClip();");
            sb.AppendSpaceLine(2, "}");
            #endregion

            //#region Where
            //sb.AppendSpaceLine(2, string.Format("private WhereClip BuildWhere({0}_Condition condition)", TableName));
            //sb.AppendSpaceLine(2, "{");
            //sb.AppendSpaceLine(3, "WhereClipBuilder where = new WhereClipBuilder();");

            //foreach (var col in Columns)
            //{
            //    if (col.TypeName.ToLower() == "string")
            //    {
            //        sb.AppendSpaceLine(3, "if (!string.IsNullOrEmpty(condition." + col.ColumnName + "))");
            //        //sb.AppendSpaceLine(3, "{");
            //    }
            //    else
            //    {
            //        sb.AppendSpaceLine(3, "if (condition." + col.ColumnName + " != null)");
            //        //sb.AppendSpaceLine(3, "{");
            //    }
            //    sb.AppendSpaceLine(4, "where.And(" + TableName + "._." + col.ColumnName + " == condition." + col.ColumnName + ");");
            //    //如果是datetime
            //    if (col.TypeName.ToLower().Contains("datetime"))
            //    {
            //        sb.AppendSpaceLine(3, "if (condition." + col.ColumnName + "_Start != null)");
            //        sb.AppendSpaceLine(4, "where.And(" + TableName + "._." + col.ColumnName + " >= condition." + col.ColumnName + "_Start);");

            //        sb.AppendSpaceLine(3, "if (condition." + col.ColumnName + "_End != null)");
            //        sb.AppendSpaceLine(4, "where.And(" + TableName + "._." + col.ColumnName + " <= condition." + col.ColumnName + "_End);");
            //    }


            //    //sb.AppendSpaceLine(3, "}");
            //}
            //sb.AppendSpaceLine(3, "return where.ToWhereClip();");
            //sb.AppendSpaceLine(2, "}");
            //#endregion


            #region Order
            sb.AppendSpaceLine(2, string.Format(" protected override OrderByClip BulidOrderBy({0}_Condition condition)", TableName));
            sb.AppendSpaceLine(2, "{");

            sb.AppendSpaceLine(3, "OrderByClip orderBy = null;");
            sb.AppendSpaceLine(3, "if (condition.OrderBy != " + TableName + "_Condition.OrderByEnum.Null)");
            sb.AppendSpaceLine(3, "{");
            sb.AppendSpaceLine(4, " var orderByOp = condition.OrderByDesc ? OrderByOperater.DESC : OrderByOperater.ASC;");
            sb.AppendSpaceLine(4, "orderBy = new OrderByClip(condition.OrderBy.ToString(), orderByOp);");
            sb.AppendSpaceLine(3, "}");
            sb.AppendSpaceLine(3, "return orderBy;");
            sb.AppendSpaceLine(2, "}");
            #endregion
            sb.AppendSpaceLine(2, "#endregion");

            return sb.Value;
        }
    }
}
